package edu.bu.cs673.superkids123.common.controller;

import java.util.Calendar;
import java.util.List;

import edu.bu.cs673.superkids123.AbstractController;
import edu.bu.cs673.superkids123.AbstractFrame;
import edu.bu.cs673.superkids123.children.DataObjectAccess.PlayTimeManager;
import edu.bu.cs673.superkids123.children.model.PlayTime;
import edu.bu.cs673.superkids123.common.DataObjectAccess.ChildManager;
import edu.bu.cs673.superkids123.common.DataObjectAccess.ParentManager;
import edu.bu.cs673.superkids123.common.controller.exceptions.PlayedTooLongException;
import edu.bu.cs673.superkids123.common.model.Child;
import edu.bu.cs673.superkids123.common.model.User;

public class AuthenticationController extends AbstractController {

	private int MILLI_SEC_IN_MINUTE = 60000;
	
	private User currentUser = null;
	private long sessionStartTime = 0;

	private int totalTime;

	public AuthenticationController(AbstractFrame mainFrame) {
		super(mainFrame);
	}

	public User getCurrentUser() {
		return currentUser;
	}
	
	public void checkPlayTime() throws PlayedTooLongException {
		// Check to see if current user went over limits
		if (currentUser != null && currentUser instanceof Child) {
			if (getPlayTimeRemaining() == 0) {
				throw new PlayedTooLongException();
			}
		}
	}
	
	/**
	 * Method to calculate how much play time a child has left
	 * 
	 * @return The time remaining for the child in minutes
	 * 		   This value will be -1 if the child has no limits, 0 if they
	 * 		   are out of time or an int value with time remaining
	 */
	public int getPlayTimeRemaining() {
		if (currentUser != null && currentUser instanceof Child) {
			long currentTime = (System.currentTimeMillis() - sessionStartTime) / MILLI_SEC_IN_MINUTE;
			long playTimePerDay = ((Child) currentUser).getPlayTimePerDay();
			long timeRemaining = playTimePerDay - (currentTime + totalTime);
		
			if (playTimePerDay == 0) return -1;
			else if (timeRemaining < 0) return 0;
			else return new Long(timeRemaining).intValue();
		}
		// Fall back to no limits
		return -1;
	}
	
	/**
	 * Method to return how much play time a child is allowed in a day
	 * 
	 * @return The time remaining for the child
	 * 		   This value will be 0 if the child has no limits
	 * 		   or an int value with total time allowed in a day
	 */
	public int getPlayTimeAllowedPerDay() {
		if (currentUser != null && currentUser instanceof Child) {
			return ((Child) currentUser).getPlayTimePerDay();
		}
		// Fall back to no limits
		return 0;
	}
	
	public void login(User user) throws PlayedTooLongException {
		totalTime = 0;
		if (user != null && user instanceof Child) {
			Calendar today = Calendar.getInstance();
			today.set(Calendar.HOUR, 0);
			today.set(Calendar.MINUTE, 0);
			today.set(Calendar.SECOND, 0);
			today.set(Calendar.MILLISECOND, 0);
			
			List<PlayTime> playTimes = PlayTimeManager.getPlayTime((Child) user, today.getTime());
			for (int i = 0; i < playTimes.size(); i++) {
				totalTime += playTimes.get(i).getTimePlayed();
			}
			
			int playTimePerDay = ((Child) user).getPlayTimePerDay();
			if (playTimePerDay != 0 && totalTime > playTimePerDay) {
				throw new PlayedTooLongException();
			}
		}
		
		currentUser = user;
		
		// The session start time
		sessionStartTime = System.currentTimeMillis();
	}

	public void logout() {
		if (currentUser != null && currentUser instanceof Child) {
			long milliSeconds = System.currentTimeMillis() - sessionStartTime;
			int timePlayed = Long.valueOf(milliSeconds / MILLI_SEC_IN_MINUTE).intValue();
			PlayTimeManager.addPlayTime((Child) currentUser, timePlayed);
		}
		
		currentUser = null;
	}

	public boolean areParentsInitialized() {
		return ParentManager.getParentCount().longValue() != 0;
	}

	public boolean areChildrenInitialized() {
		return ChildManager.getChildCount().longValue() != 0;
	}
}
